package controllers;

import java.util.ArrayList;
import asyncsenders.InvitesSender;
import dataobjects.Invite;
import dataobjects.User;
import dbaccessors.DBAccessor;

/**
 * Implemented as a singleton.
 * 
 */
public class UserController {

	private static UserController instance = null;
	private InvitesSender invitesSender;

	private UserController() {
		this.invitesSender = new InvitesSender();
	}

	public static UserController getInstance() {
		if (instance == null) {
			instance = new UserController();
		}
		return instance;
	}

	// methods

	public User findUserByCard(int cid) {
		// TODO
		return null;
	}

	public ArrayList<User> findUserByWishList(String username) {
		// TODO
		return null;
	}

	public boolean isLoggedIn(String username) {
		// TODO
		return false;
	}

	public boolean login(String username, String password) {
		return DBAccessor.getInstance().login(username, password);
	}

	public boolean register(String username, String name, String mail,
			String password) {
		System.out.println("register UserController");
		return DBAccessor.getInstance()
				.register(username, name, mail, password);
	}

	public boolean logout(String username) {
		System.out.println("logout: " + username);
		return DBAccessor.getInstance().logout(username);
	}

	public User getUser(String username) {
		User ans = DBAccessor.getInstance().getUserByName(username);
		return ans;
	}

	public ArrayList<User> findMatchingUsers(String username) {

		ArrayList<User> ans = DBAccessor.getInstance().findMatchingUsers(
				username);
		return ans;
	}

	public boolean createTradeInvite(String requestingUser,
			String acceptingUser, int givesID, int getsID) {
		// update DB
		boolean ans = DBAccessor.getInstance().createTradeInvite(
				requestingUser, acceptingUser, givesID, getsID);
		// notify to accepting user
		if (ans)
			this.invitesSender.sendInvite(acceptingUser);
		return ans;
	}

	public ArrayList<Invite> getInvites(String username) {
		return DBAccessor.getInstance().getInvites(username);
	}

	public Invite confirmInvite(String askUsername, String recievingUsername,
			int wantInstanceID, int giveInstanceID, String type) {
		// update DB
		Invite ans = DBAccessor.getInstance().confirmInvite(askUsername,
				recievingUsername, wantInstanceID, giveInstanceID, type);
		// Notify to askUsername
		if (type.equals("TRADE"))
			this.invitesSender.confirmTrade(askUsername, recievingUsername,
					ans.giveCard.name, ans.wantCard.name);
		else {
			GameController.getInstance().startNewGame(askUsername, recievingUsername, giveInstanceID, wantInstanceID, type); //start new game
			this.invitesSender.confirmGame(ans); //notify to waiting user
		}
		return ans;
	}

	public boolean declineInvite(String askUsername, String recievingUsername,
			int wantInstanceID, int giveInstanceID, String type) {
		// update DB
		boolean ans = DBAccessor.getInstance().declineInvite(askUsername,
				recievingUsername, wantInstanceID, giveInstanceID, type);
		// Notify to askUsername
		if (type.equals("TRADE")) { // decline trade request
			String giveCardName = DBAccessor.getInstance().getCardName(
					giveInstanceID);
			String wantCardName = DBAccessor.getInstance().getCardName(
					wantInstanceID);
			this.invitesSender.declineTrade(askUsername, recievingUsername,
					giveCardName, wantCardName);
		} else { // decline game request
			this.invitesSender.declineGame(askUsername);
		}
		return ans;
	}

	public Invite createGameInvite(String requestingUser, String acceptingUser,
			int givesID, int getsID, String type) {
		// update DB
		Invite ans = DBAccessor.getInstance().createGameInvite(requestingUser,
				acceptingUser, givesID, getsID, type);
		// notify to accepting user
		if (ans != null)
			this.invitesSender.sendInvite(acceptingUser);
		return ans;
	}

	public boolean cancelGameInvite(String askingUsername,
			String receivingUsername, int giveCardID, int wantCardID,
			String type) {
		return DBAccessor.getInstance().cancelGameInvite(askingUsername,
				receivingUsername, giveCardID, wantCardID, type);
	}

}
